home *** CD-ROM | disk | FTP | other *** search
-
-
- Generic Application Template
- (preliminary)
- Tom Davis
- December 13, 1991
-
- Many applications, such as text editors, drawing packages, paint
- programs, and word processors have a similar form. The user reads a
- file, modifies it, and writes the results. Unfortunately, this model
- can get quite complicated. What if the user hasn't got write
- permission? What if there is some I/O error on the write? What if the
- user hasn't yet specified a name? Is the user in view-only mode?
-
- The generic application will provide a file opening template that is
- reasonable, but which can be modified by users. For example, the
- generic application goes into view_only mode if an unwriteable file is
- loaded. Some applications may want to do otherwise.
-
- The generic application will work on all machines, in singlebuffer or
- doublebuffer modes, and in RGB or color-index modes.
-
- The generic program will catch various quit and kill signals from UNIX
- and the window manager, and should treat them appropriately. This
- behavior is optional.
-
- The application is as user-interface-free as possible. It uses the
- showcase libui to make pulldown menues and the confirmer dialog box.
- Both can be removed/replaced easily. To collect a file name it uses
- the showcase browse gizmo, but the file name collection routine can be
- replaced.
-
- The "guts" of the generic application is a program that draws a black
- window and draws a red cross on it.
-
- What follows is a description of what the generic application does,
- followed by a description of how to port your own application to this
- template. I'm very interested in feedback and improvements.
-
- ----------
-
- The following state is maintained:
-
- directory from which the application was launched
- the application's current directory
- whether the application is in view_only mode
- the current file name (or NONE, if there isn't one)
- whether the file has been modified
- is the application making checkpoint (see definitions) files
- is the application making backup (see definitions) files
-
- ----------
-
- Pull-down menus:
-
- The generic application will provide a pull-down menu containing the
- following commands:
-
- NEW
- OPEN
- SAVE
- SAVE AS
- INSERT
- PRINT
- QUIT
-
- NEW:
-
- In VIEW_ONLY mode, the command is not allowed.
-
- A dirty-file check (see definitions) is performed.
-
- If the NEW command is not aborted, the current file's data is cleared,
- the application is taken out of view_only mode, and the current file
- name is set to NONE. The dirty_file flag is cleared.
-
- OPEN:
-
- A dirty-file check (see definitions) is performed.
-
- If the OPEN command is not aborted, a new file name is obtained, and
- the open-status (see definitions) of the file with the name collected
- is checked.
-
- If the file name collection fails, abort the OPEN command.
-
- If the file does not exist or cannot be read:
-
- In VIEW_ONLY mode, abort the OPEN command.
-
- If the user cannot create a file with that name, or if the
- file already exists, but cannot be read, the OPEN command
- is aborted.
-
- The dirty_file flag is cleared.
-
- The data in the buffer is cleared.
-
- If the user can create such a file, view_only mode is turned
- off, and the current file name is set to the new name.
-
- If the file does exist and can be read:
-
- The dirty_file flag is cleared.
-
- The data in the buffer is cleared.
-
- If it cannot be written, the user is informed, view_only mode
- is turned on, and the file name is set to the given name.
-
- If it can be written, view_only mode is turned off, unless
- VIEW_ONLY mode is on, and the file name is set to the given
- name.
-
- Read the file.
-
- SAVE:
-
- In VIEW_ONLY mode, the command is aborted.
-
- If the current file name is NONE, collect a file name. Find its
- open-status. If it can't be written or created, or if the collection
- fails, inform the user and abort.
-
- If there was a current file, check its open-status, possibly resetting
- the view_only flag. If the file can't be written or created, inform
- the user and abort.
-
- The buffer is written to a file with the current file name. If no
- error occurs, the dirty flag is turned off.
-
- SAVE-AS:
-
- (This command works in VIEW_ONLY mode.)
-
- A file name is collected, and its open-status is determined. If the
- collection of the name fails, abort the SAVE-AS command.
-
- If the file exists but can't be written, or if it does not exist and
- cannot be created, the user is informed, and the command aborts.
-
- Otherwise, write the file. If no write error occurs, clear the
- dirty_flag, and unless VIEW_ONLY mode is turned on, set the current
- file name to the new name, and turn view_only mode off.
-
- INSERT:
-
- In view-only mode, abort.
-
- Collect a file name and check its open-status.
-
- If the collection fails, abort the INSERT command.
-
- If the file exists and can be read, call the user routine that inserts
- the contents of the file. Presumably, this sets the dirty flag.
-
- PRINT:
-
- A print file name is generated from the user's PID and a counter. The
- open status of $TMPDIR/filename is determined. If it can be written
- or created, the user's print routine is called with the file name. It
- is up to the print command to issue the lp command or whatever.
-
- QUIT:
-
- A dirty-file check (see definitions) is performed.
-
- Unless the QUIT command is aborted, the program exits.
-
- ----------
-
- Startup:
-
- The application is invoked as:
-
- genericapplication -[vf] [filename]
-
- If the -v flag is set, the application is started in VIEW_ONLY mode.
- If the -f flag is specified, the application is started in the
- foreground to aid in both debugging and for use in certain other
- conditions.
-
- If the application is in VIEW_ONLY mode, a file name must be specified
- and the file must be readable, or there's an error, and the
- application just won't start up.
-
- If a filename is specified, it is exactly the same as if the
- application were opened, the open command issued, and the given file
- name was collected.
-
- If no filename is specified, the current file name is set to NONE.
-
- ----------
-
- Signals:
-
- The generic application will catch the common UNIX signals. When
- caught, the user will be informed of the error, and be given a chance
- to save the contents of the buffer.
-
- If the application recieves a WINQUIT or WINSHUT command, it should be
- treated in exactly the same way as a QUIT command.
-
- ----------
-
- Backup and Checkpoint files:
-
- The user code sets the flags MAKE_BACKUPS and MAKE_CHECKPOINTS. Each
- time a NEW or OPEN command is issued, internal variables called
- "make_backups" and "make_checkpoints" are set that are true only if
- creation/writing of those files should be done.
-
- ----------
-
- Utility commands:
-
- void resizepulldowns();
- long getfileopenstatus(char *filename);
-
- /* getfileopenstatus() returns a mask with the following bits
- * (more may follow):
- *
- * #define FILE_EXISTS 1
- * #define CAN_WRITE_FILE 2
- */
-
- Visible flags:
-
- VIEW_ONLY, view_only
- MAKE_BACKUPS, make_backups
- MAKE_CHECKPOINTS, make_checkpoints
- dirty_file
-
- Visible variables:
-
- char *currentfilename;
-
- User-supplied routines:
-
- void clearbuffer();
- long readfile(char *filename);
- long makebackupname(char *backupname, const char *filename);
- long makecheckpointname(char *checkpointname, const char *filename);
- long writefile(char *filename);
- long insertfile(char *filename);
- long printfile(char *printfilename);
- long errorwritefile(char *filename);
- /* errorwritefile() may be identical to writefile(), but it may want
- * to take into account possible internal data corruption.
- */
- void help();
- /* help() is the command called if the user asks for generic help. */
-
- ----------
-
- Definitions:
-
- backup file: A copy of the original file saved when the original
- is read. It typically has an extension like ".bak", and is written in
- the same directory as the original file.
-
- buffer: This refers to the data stored in the program's internal data
- structures, as opposed to what is saved in a file.
-
- checkpoint file: A version of the file that is occasionally written to
- disk automatically to prevent against errors. It typically has an
- extension like ".ckp", and is written in the same directory as the
- original file.
-
- collecting a file name: In the generic application, the showcase
- browsegizmo is used to get a file name and perhaps a new directory path.
- If '~' appears in the name, it is expanded. The collection of a name
- can fail if the user presses the equivalent of a "Cancel" button.
-
- dirty-file check: If the current file has no modifications, nothing is
- done. If it is modified, the user is asked about saving the changes.
- His options are "Yes" (save the changes and continue the command), "No"
- (throw away the changes and continue the command), and "Cancel" (abort
- the command).
-
- file names: relative directory paths and the '~' character may be used
- in file names.
-
- open-status: The open-status includes: Does the user have read
- permission on the file? Write permission? Does the file exist? If not,
- can the user create a file in that directory?
-
- read the file: Determine the values of the flags make_backups and
- make_checkpoints. If make_backups is set, call the user routine that
- makes a backup file. The file is read, and any errors are reported to
- the user. 1 is returned on success; 0 on failure. It is up to the
- user-supplied reading command to decide what to do with the buffer's
- contents in the event of some read error; perhaps it will be cleared,
- or perhaps as much valid data as possible is retained.
-
- view-only mode: There are two levels of view-only. The application can
- be opened in VIEW_ONLY mode, in which case no changes can be made to
- the buffer. If the application is not in this generic VIEW_ONLY mode,
- there may be times when edits are disallowed anyway -- for example if
- the file currently loaded is unwriteable. The flag for this secondary
- level is called "view_only" (lower case). Inside the application, only
- the view_only flag needs to be examined. If VIEW_ONLY is true,
- view_only will always be true.
-
- write the file: Try to write the current data to the currently-opened
- file. Return 0 if any write-error occurs. Provide as much feedback as
- possible about the cause of the error.
-
- ----------
-
- Using the generic application.
-
- Most of your changes will be to the file application.c, but if you want
- to use the pull-down menues, you will probably want to add entries in
- pulldown.c, and if you want additional speed keys (alt-something), you
- will want to mess with doexec.c.
-
- If you need to make significant changes to the other files, let me know.
- I tried to keep things as generic as possible.
-
- To compile with the pulldown menu or the generic confirmer, you'll need
- the showcase libui.a library. There's a working version in
- bedlam.asd:~davis/libui/libui.a.
-
- The simplest port involves rewriting mainloop(), initgraphics(),
- handleredraw(), and providing routines for readfile(), writefile(), etc.
- If your application does not do some of the things like printing,
- file insertion, etc., simply put a zero in the appropriate slot in
- the structure called entries.
-
- Read the comments in application.c -- they give a pretty good idea of
- its structure.
-
- If you want to use a gizmo, the code for a generic gizmo is in the
- subdirectory called gizmos. In the generic program, the gizmo is
- capable of sending a single command -- TOUCHME. Use any interface you
- like in the gizmo. Unfortuantely, the gizmo documentation isn't very
- good.
-
- ----------
-
- Possible Future Improvements:
-
- It would be nice if the user had the option to either overwrite the file
- or write a copy and then rename it to be the new file (if that's
- possible). For now, it isn't. For this to work, the code must be
- careful to preserve file permissions, and watch out for files with
- multible links.
-
- Provide a reopen file list for quick access to old file names.
-
- It would be good to have a generic WorkSpace icon.
-